//=============================================================================
//	THIS SOURCE CODE IS PROPRIETARY INFORMATION BELONGING TO INTERVIDEO, INC.
// 	ANY USE INCLUDING BUT NOT LIMITED TO COPYING OF CODE, CONCEPTS, AND/OR
//	ALGORITHMS IS PROHIBITED EXCEPT WITH EXPRESS WRITTEN PERMISSION BY THE 
//	COMPANY.
//
// 	THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// 	KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// 	IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// 	PURPOSE.
//
// 	Copyright (c) 1998 - 2005  InterVideo Corporation.  All Rights Reserved.
//
//-----------------------------------------------------------------------------

#ifndef _UTILCVT_H
#define _UTILCVT_H

#ifdef _XENON
#define USE_BIGENDIAN
#endif

class CUTILcvt
	{
public:
	inline static void Endian(short *num, const void *src);
	inline static void Endian(unsigned short *num, const void *src);
	inline static void Endian(long *num, const void *src);
	inline static void Endian(unsigned long *num, const void *src);
	inline static void Endian(unsigned short& num);
	inline static void Endian(unsigned long&  num);
	inline static void EndianAdd(const void *src, long offset);
	inline static int IsLittleEndian();
	inline static int IsBigEndian() { return !IsLittleEndian(); }
	inline static void LittleEndian(short *num, const void *src);
	inline static void LittleEndian(unsigned short *num, const void *src);
	inline static void LittleEndian(long *num, const void *src);
	inline static void LittleEndian(unsigned long *num, const void *src);
	inline static void Msec2Hmsf(void* hmsf,unsigned long msec,unsigned long tc_flag);
	inline static void Hmsf2Msec(unsigned long* msec,const void* hmsf,unsigned long tc_flag);
	inline static void Msec2Bcd(void* bcd,unsigned long msec,unsigned long tc_flag);
	inline static void Bcd2Msec(unsigned long* msec,const void* bcd);
	inline static void Hmsf2Bcd(void* bcd,const void* hmsf);
	inline static void Bcd2Hmsf(void* hmsf,const void* bcd);
	inline static void ChangeEndian(short *num, const void *src);
	inline static void ChangeEndian(unsigned short *num, const void *src);
	inline static void ChangeEndian(long *num, const void *src);
	inline static void ChangeEndian(unsigned long *num, const void *src);
	};

void CUTILcvt::Endian(short *num, const void *src)
	{
#ifdef USE_BIGENDIAN
	*num = *((short *)src);
#else
	((char *)num)[0] = ((char *)src)[1];
	((char *)num)[1] = ((char *)src)[0];
#endif
	}

void CUTILcvt::Endian(unsigned short *num, const void *src)
	{
#ifdef USE_BIGENDIAN
	*num = *((unsigned short *)src);
#else
	((char *)num)[0] = ((char *)src)[1];
	((char *)num)[1] = ((char *)src)[0];
#endif
	}

void CUTILcvt::Endian(long *num, const void *src)
	{
#ifdef USE_BIGENDIAN
	*num = *((long *)src);
#else
	((char *)num)[0] = ((char *)src)[3];
	((char *)num)[1] = ((char *)src)[2];
	((char *)num)[2] = ((char *)src)[1];
	((char *)num)[3] = ((char *)src)[0];
#endif
	}

void CUTILcvt::Endian(unsigned long *num, const void *src)
	{
#ifdef USE_BIGENDIAN
	*num = *((unsigned long *)src);
#else
	((char *)num)[0] = ((char *)src)[3];
	((char *)num)[1] = ((char *)src)[2];
	((char *)num)[2] = ((char *)src)[1];
	((char *)num)[3] = ((char *)src)[0];
#endif
	}

void CUTILcvt::Endian(unsigned short& num)
	{
#ifndef USE_BIGENDIAN
	unsigned short src = num;
	num = (src>>8)&0x00ff | (src<<8)&0xff00;
#endif
	}

void CUTILcvt::Endian(unsigned long& num)
	{
#ifndef USE_BIGENDIAN
	unsigned long src = num;
	num = (src>>24)&0xff | (src >>8)&0xff00 |(src <<24)&0xff000000 | (src<<8)&0xff0000;
#endif
	}

void CUTILcvt::EndianAdd(const void *src, long offset)
	{
	long value;

	Endian(&value,src);
	value += offset;
	Endian((long *)src,&value);
	}

int CUTILcvt::IsLittleEndian()
	{
	long num = 0x01020304;

	return *(char *)&num==0x04;
	}

void CUTILcvt::LittleEndian(short *num, const void *src)
	{
	if(IsLittleEndian())
		{
		((char *)num)[0] = ((char *)src)[0];
		((char *)num)[1] = ((char *)src)[1];
		}
	else
		Endian(num,src);
	}

void CUTILcvt::ChangeEndian(short *num, const void *src)
	{
	((char *)num)[1] = ((char *)src)[0];
	((char *)num)[0] = ((char *)src)[1];
	}

void CUTILcvt::LittleEndian(unsigned short *num, const void *src)
	{
	if(IsLittleEndian())
		{
		((char *)num)[0] = ((char *)src)[0];
		((char *)num)[1] = ((char *)src)[1];
		}
	else
		Endian(num,src);
	}

void CUTILcvt::ChangeEndian(unsigned short *num, const void *src)
	{
	((char *)num)[1] = ((char *)src)[0];
	((char *)num)[0] = ((char *)src)[1];
	}

void CUTILcvt::LittleEndian(long *num, const void *src)
	{
	if(IsLittleEndian())
		{
		((char *)num)[0] = ((char *)src)[0];
		((char *)num)[1] = ((char *)src)[1];
		((char *)num)[2] = ((char *)src)[2];
		((char *)num)[3] = ((char *)src)[3];
		}
	else
		Endian(num,src);
	}

void CUTILcvt::ChangeEndian(long *num, const void *src)
	{
	((char *)num)[3] = ((char *)src)[0];
	((char *)num)[2] = ((char *)src)[1];
	((char *)num)[1] = ((char *)src)[2];
	((char *)num)[0] = ((char *)src)[3];
	}

void CUTILcvt::LittleEndian(unsigned long *num, const void *src)
	{
	if(IsLittleEndian())
		{
		((char *)num)[0] = ((char *)src)[0];
		((char *)num)[1] = ((char *)src)[1];
		((char *)num)[2] = ((char *)src)[2];
		((char *)num)[3] = ((char *)src)[3];
		}
	else
		Endian(num,src);
	}

void CUTILcvt::ChangeEndian(unsigned long *num, const void *src)
	{
	((char *)num)[3] = ((char *)src)[0];
	((char *)num)[2] = ((char *)src)[1];
	((char *)num)[1] = ((char *)src)[2];
	((char *)num)[0] = ((char *)src)[3];
	}

void CUTILcvt::Msec2Hmsf(void* hmsf,unsigned long msec, unsigned long tc_flag)
	{
	unsigned long sec = msec/1000;
	msec %= 1000;
	((char*)hmsf)[0] = (char)(sec/3600);
	((char*)hmsf)[1] = (char)(sec%3600/60);
	((char*)hmsf)[2] = (char)(sec%3600%60);
	((char*)hmsf)[3] = (char)(tc_flag==1 ? msec/40 : tc_flag==3 ? msec*3/100 : 0);
	}

void CUTILcvt::Hmsf2Msec(unsigned long* msec,const void* hmsf, unsigned long tc_flag)
	{
     unsigned char *p= (unsigned char*) hmsf;
	 *msec = (unsigned long)p[0]*3600000+(unsigned long)p[1]*60000+(unsigned long)p[2]*1000;
	 unsigned long f = p[3];
	 *msec += tc_flag==1 ? f*40 : tc_flag==3 ? f*100/3 : 0;
	}

void CUTILcvt::Bcd2Msec(unsigned long* msec,const void* bcd)
	{
	unsigned long *p = (unsigned long*) bcd;
	unsigned long h = ((*p&0x000000f0)>>4)*10+(*p&0x0000000f);
	unsigned long m = ((*p&0x0000f000)>>12)*10+((*p&0x00000f00)>>8);
	unsigned long s = ((*p&0x00f00000)>>20)*10+((*p&0x000f0000)>>16);
	unsigned long f = ((*p&0x30000000)>>28)*10+((*p&0x0f000000)>>24);
	unsigned long tc_flag = (*p>>30)&3;
	*msec = (h*3600+m*60+s)*1000;
	*msec += tc_flag==1 ? f*40 : tc_flag==3 ? f*100/3 : 0;
	}

void CUTILcvt::Msec2Bcd(void* bcd,unsigned long msec, unsigned long tc_flag)
	{
	unsigned long *p =(unsigned long*)bcd;
	unsigned long f;

	switch(tc_flag)
		{
	case 1:
		f = msec%1000/40;
		break;
	case 3:
		f = msec%1000*3/100;
		break;
	default:
		tc_flag = 0;
		f = 0;
		break;
		}
	*p = (tc_flag<<30) | (f/10<<28) | (f%10<<24);
	*p|= ((msec%60000/10000)<<20)|((msec%10000/1000)<<16);
	*p|= ((msec%3600000/600000)<<12)|((msec%600000/60000)<<8);
	*p|= ((msec%360000000/36000000)<<4)|(msec%36000000/3600000);
	}

void CUTILcvt::Hmsf2Bcd(void* bcd,const void* hmsf)
	{
	  ((unsigned char*)bcd)[0] = (((unsigned char*)hmsf)[0]/10)<<4|((unsigned char*)hmsf)[0]%10;
	  ((unsigned char*)bcd)[1] = (((unsigned char*)hmsf)[1]/10)<<4|((unsigned char*)hmsf)[1]%10;
	  ((unsigned char*)bcd)[2] = (((unsigned char*)hmsf)[2]/10)<<4|((unsigned char*)hmsf)[2]%10;
	  ((unsigned char*)bcd)[3] = (((unsigned char*)hmsf)[3]/10)<<4|((unsigned char*)hmsf)[3]%10;
	}

void CUTILcvt::Bcd2Hmsf(void* hmsf,const void* bcd)
	{
	  ((unsigned char*)hmsf)[0] = ((((unsigned char*)bcd)[0]&0xf0)>>4)*10+((unsigned char*)bcd)[0]&0x0f;
	  ((unsigned char*)hmsf)[1] = ((((unsigned char*)bcd)[1]&0xf0)>>4)*10+((unsigned char*)bcd)[1]&0x0f;
	  ((unsigned char*)hmsf)[2] = ((((unsigned char*)bcd)[2]&0xf0)>>4)*10+((unsigned char*)bcd)[2]&0x0f;
	  ((unsigned char*)hmsf)[3] = ((((unsigned char*)bcd)[3]&0xf0)>>4)*10+((unsigned char*)bcd)[3]&0x0f;
	}

#endif /* _UTILCVT_H */
